/**
 * 
 */
package com.dalonedrow.engine.systems.base;

import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.dalonedrow.engine.sprite.base.SimplePoint;
import com.dalonedrow.engine.ui.base.MessageWindow;
import com.dalonedrow.engine.ui.base.SmallMessageViewer;
import com.dalonedrow.engine.ui.base.SmallOptionsMessageViewer;
import com.dalonedrow.engine.ui.base.ToolTip;
import com.dalonedrow.engine.ui.base.View;
import com.dalonedrow.engine.ui.base.panel.Panel;
import com.dalonedrow.globalvariables.constants.hq.GlobalConstants;
import com.dalonedrow.module.hq.DawnQuestGame;

/**
 * @author Donald
 */
public final class Interface implements InputProcessor {
	/** the one and only instance of the <code>Render</code> class. */
	private static Interface	instance;
	/**
	 * Render Gives access to the singleton instance of {@link Interface}.
	 * @return {@link Interface}
	 */
	public static Interface getInstance() {
		if (Interface.instance == null) {
			Interface.instance = new Interface();
		}
		return Interface.instance;
	}
	/** the index of the current view displayed. */
	private int			currentView;
	private Panel		dialog;
	/** the current mouse location. can be null. */
	private SimplePoint	mouseLoc;
	/** the view flags. */
	private long		viewFlags	= 0;
	/** the list of {@link View}s displayed. */
	private View[]		views		= new View[0];
	/** Hidden constructor. */
	private Interface() {}
	/**
	 * Adds a {@link View} to the interface.
	 * @param view the {@link View}
	 */
	public void addView(final View view) {
		View[] dest = new View[views.length + 1];
		System.arraycopy(views, 0, dest, 0, views.length);
		dest[views.length] = view;
		views = dest;
		dest = null;
	}
	/**
	 * Assigns a view flag.
	 * @param flag the flag
	 */
	public void assignViewFlag(final long flag) {
		viewFlags |= flag;
	}
	/** Clears all view flags that were assigned. */
	public void clearViewFlags() {
		viewFlags = 0;
	}
	/** Update the game. */
	public void gameUpdate() {
		handleMouseOver();
	}
	/**
	 * Gets the current view being displayed.
	 * @return {@link View
	 */
	public View getCurrentView() {
		return views[currentView];
	}
	/**
	 * Checks the mouse position and changes the cursor when over a GUI
	 * component.
	 */
	public void handleMouseOver() {
		if (mouseLoc != null) {
			// ARE CONTROLS BLOCKED
			if (hasViewFlag(GlobalConstants.VW_03_CONTROLS_BLOCKED)
					|| hasViewFlag(GlobalConstants.VW_05_LOADWINDOW)) {
				ProjectConstants.getInstance().setCursor(
						GlobalConstants.CURSOR_03_WAIT);
			} else {
				ProjectConstants.getInstance().setCursor(
						GlobalConstants.CURSOR_00_DEFAULT);
				float x = (float) mouseLoc.getX();
				float y = GlobalConstants.SCREEN_HEIGHT
						- (float) mouseLoc.getY();
				if (hasViewFlag(GlobalConstants.VW_01_MSGWINDOW)) {
					// if (MessageWindow.getInstance().contains(x, y)) {
					// MessageWindow.getInstance().handleMouseOver(x, y);
					// }
				} else if (hasViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW)) {
					if (SmallMessageViewer.getInstance().contains(x, y)) {
						SmallMessageViewer.getInstance().handleMouseOver(x, y);
					}
				} else if (hasViewFlag(GlobalConstants.VW_06_SMLOPTMSGWINDOW)) {
					if (SmallOptionsMessageViewer.getInstance().contains(
							x, y)) {
						SmallOptionsMessageViewer.getInstance()
								.handleMouseOver(
										x, y);
					}
				} else if (hasViewFlag(GlobalConstants.VW_07_DLG_WINDOW)
						&& dialog != null) {
					if (dialog.contains(x, y)) {
						dialog.handleMouseOver(x, y);
					}
				} else {
					if (views[currentView] != null) {
						views[currentView].handleMouseOver(x, y);
					}
				}
			}
			ProjectConstants.getInstance().switchCursor();
		}
	}
	/**
	 * Determines if the {@link Interface} has a specific view flag set.
	 * @param flag the flag
	 * @return true if the flag was set; false otherwise
	 */
	public boolean hasViewFlag(final long flag) {
		return (viewFlags & flag) == flag;
	}
	public void hideDialog(final Panel c) {
		if (c != null
				&& dialog != null
				&& c.getId() == dialog.getId()) {
			dialog = null;
		}
		removeViewFlag(GlobalConstants.VW_07_DLG_WINDOW);
	}
	/** Hides the message window. */
	public void hideMessageWindow() {
		removeViewFlag(GlobalConstants.VW_01_MSGWINDOW);
	}
	/** Hides the message window. */
	public void hideSmallMessageWindow() {
		removeViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW);
	}
	/** Hides the message window. */
	public void hideSmallOptionsMessageWindow() {
		removeViewFlag(GlobalConstants.VW_06_SMLOPTMSGWINDOW);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean keyDown(int keycode) {
		return true;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean keyTyped(final char character) {
		// IS GAME PAUSED
		System.out.println("keyTyped("+character);
		// ARE CONTROLS BLOCKED
		if (!hasViewFlag(GlobalConstants.VW_03_CONTROLS_BLOCKED)
				&& !hasViewFlag(GlobalConstants.VW_05_LOADWINDOW)) {
			// IS THE MESSAGEWINDOW DISPLAYED?
			if (hasViewFlag(GlobalConstants.VW_01_MSGWINDOW)) {
				// ignore any key presses except enter
				switch (character) {
				case Keys.ENTER:
					hideMessageWindow();
					break;
				case Keys.ESCAPE:
					DawnQuestGame.getInstance().end();
					break;
				default:
					break;
				}
			} else if (hasViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW)) {
				// ignore any key presses except enter
				switch (character) {
				case Keys.ENTER:
					SmallMessageViewer.getInstance().fireMouseClickThruEnter();
					break;
				case Keys.ESCAPE:
					DawnQuestGame.getInstance().end();
					break;
				default:
					break;
				}
			} else {
				if (views[currentView] != null) {
					views[currentView].keyTyped(character);
				}
			}
		}
		return true;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean keyUp(int keycode) {
		// TODO Auto-generated method stub
		return true;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean mouseMoved(int screenX, int screenY) {
		// TODO Auto-generated method stub
		return false;
	}
	/**
	 * Prepares the {@link View} for the rendering loop.
	 * @throws Exception if an error occurs
	 */
	public void prepareForRendering() throws Exception {
		if (views[currentView] != null) {
			views[currentView].prepareForRendering();
		}
		if (!hasViewFlag(GlobalConstants.VW_05_LOADWINDOW)) {
			if (hasViewFlag(GlobalConstants.VW_01_MSGWINDOW)) {
				MessageWindow.getInstance().prepareForRendering();
			} else if (hasViewFlag(GlobalConstants.VW_06_SMLOPTMSGWINDOW)) {
				SmallOptionsMessageViewer.getInstance().prepareForRendering();
			} else if (hasViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW)) {
				SmallMessageViewer.getInstance().prepareForRendering();
			} else if (hasViewFlag(GlobalConstants.VW_07_DLG_WINDOW)
					&& dialog != null) {
				dialog.prepareForRendering();
			} else if (hasViewFlag(GlobalConstants.VW_02_TOOLTIP)
					&& !hasViewFlag(GlobalConstants.VW_07_DLG_WINDOW)) {
				ToolTip.getInstance().prepareForRendering();
			}
		}
	}
	/**
	 * Removes a view flag.
	 * @param flag the flag
	 */
	public void removeViewFlag(final long flag) {
		viewFlags &= ~flag;
	}
	public void ResetPlayerInterface() {}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean scrolled(int amount) {
		// TODO Auto-generated method stub
		return false;
	}
	/**
	 * Sets the current view displayed.
	 * @param view the id of the view displayed
	 */
	public void setCurrentView(final int view) {
		currentView = view;
	}
	/**
	 * Sets the mouse location on screen.
	 * @param pt the {@link SimplePoint} to set
	 */
	public void setMouseLoc(final int x, final int y) {
		if (mouseLoc == null) {
			mouseLoc = new SimplePoint(x, y);
		} else {
			mouseLoc.move(x, y);
		}
	}
	/**
	 * Sets the mouse location on screen.
	 * @param pt the {@link SimplePoint} to set
	 */
	public void setMouseLoc(final SimplePoint pt) {
		mouseLoc = pt;
	}
	/**
	 * Sets a view.
	 * @param index the view index
	 * @param view the {@link View}
	 */
	public void setView(final int index, final View view) {
		if (index >= views.length) {
			View[] dest = new View[index + 1];
			System.arraycopy(views, 0, dest, 0, views.length);
			views = dest;
			dest = null;
		}
		views[index] = view;
	}
	public void showDialog(final Panel c) {
		dialog = c;
		assignViewFlag(GlobalConstants.VW_07_DLG_WINDOW);
	}
	/** Shows the message window as it currently exists. */
	public void showMessageWindow() {
		assignViewFlag(GlobalConstants.VW_01_MSGWINDOW);
	}
	/**
	 * Shows the message window.
	 * @param text the text displayed in the message window
	 */
	public void showMessageWindow(final String text) {
		MessageWindow.getInstance().showMessage(text);
		assignViewFlag(GlobalConstants.VW_01_MSGWINDOW);
	}
	/** Shows the message window as it currently exists. */
	public void showSmallMessageWindow() {
		assignViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW);
	}
	/**
	 * Shows the small message window, with no callback event.
	 * @param header the message header
	 * @param msg the message
	 */
	public void showSmallMessageWindow(final String header, final String msg) {
		showSmallMessageWindow(header, msg, null);
	}
	/**
	 * Shows the small message window.
	 * @param header the message header
	 * @param msg the message
	 * @param e the callback event, can be null
	 */
	public void showSmallMessageWindow(final String header, final String msg,
			final Action e) {
		SmallMessageViewer.getInstance().showMessage(header, msg, e);
		assignViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW);
	}
	/**
	 * Shows the small message window.
	 * @param header the message header
	 * @param msg the message
	 * @param a the callback event, can be null
	 */
	public void showSmallOptionsMessageWindow(final String header,
			final String msg, final Action a) {
		SmallOptionsMessageViewer.getInstance().showMessage(header, msg, a);
		assignViewFlag(GlobalConstants.VW_06_SMLOPTMSGWINDOW);
	}
	/**
	 * Shows the small message window.
	 * @param header the message header
	 * @param msg the message
	 * @param eTrue the callback action fired when 'Yes' is clicked, can be null
	 * @param eFalse the callback action fired when 'No' is clicked, can be null
	 */
	public void showSmallOptionsMessageWindow(final String header,
			final String msg, final Action eTrue, final Action eFalse) {
		SmallOptionsMessageViewer.getInstance().showMessage(header, msg, eTrue,
				eFalse);
		assignViewFlag(GlobalConstants.VW_06_SMLOPTMSGWINDOW);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		// in android, the user has touched the screen
		return true;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean touchDragged(int screenX, int screenY, int pointer) {
		// TODO Auto-generated method stub
		return false;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean touchUp(int screenX, int screenY, int pointer, int button) {
		// in android, the user has lifted their finger; in desktop, the mouse
		// button was released
		// ARE CONTROLS BLOCKED
		if (!hasViewFlag(GlobalConstants.VW_03_CONTROLS_BLOCKED)
				&& !hasViewFlag(GlobalConstants.VW_05_LOADWINDOW)) {
			if (mouseLoc != null) {
				float x = screenX;
				float y = GlobalConstants.SCREEN_HEIGHT
						- (float) screenY;
				if (hasViewFlag(GlobalConstants.VW_01_MSGWINDOW)) {
					// if (MessageWindow.getInstance().contains(x, y)) {
					// MessageWindow.getInstance().handleMouseClick(x, y);
					// }
				} else if (hasViewFlag(GlobalConstants.VW_04_SMLMSGWINDOW)) {
					if (SmallMessageViewer.getInstance().contains(x, y)) {
						SmallMessageViewer.getInstance().touchUp(
								(int) x, (int) y, pointer, button);
					}
				} else if (hasViewFlag(GlobalConstants.VW_06_SMLOPTMSGWINDOW)) {
					if (SmallOptionsMessageViewer.getInstance().contains(
							x, y)) {
						SmallOptionsMessageViewer.getInstance().touchUp(
								(int) x, (int) y, pointer, button);
					}
				} else if (hasViewFlag(GlobalConstants.VW_07_DLG_WINDOW)
						&& dialog != null) {
					if (dialog.contains(x, y)) {
						dialog.touchUp((int) x, (int) y, pointer, button);
					}
				} else {
					if (views[currentView] != null) {
						views[currentView].touchUp((int) x, (int) y, pointer,
								button);
					}
				}
			}
		}
		return false;
	}
}
